﻿/*
 class: UBCon.Ribbon.ApplicationMenu
 * Author: Ravshan Ergashov
 * Tashkent, 2013
 */

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Linq;
using System.Windows.Data;
using System.ComponentModel;
using UBCon.Ribbon.Interfaces;

namespace UBCon.Ribbon
{
    using UBCon.Core.Enums;
    using System.Windows.Media;

    [TemplatePart(Name=AppMenuSelectedPresenterName, Type=typeof(ContentPresenter))]
    [TemplatePart(Name=AppMenuContentBorderName, Type=typeof(Border))]
    public sealed class ApplicationMenu : ListBox, IRibbonControl
    {
        //------------------------------------------------------
        //
        //  Constructors
        //
        //------------------------------------------------------
        #region Constructors
        static ApplicationMenu()
        {
            Type ownerType = typeof(ApplicationMenu);
            ApplicationMenu.DefaultStyleKeyProperty.OverrideMetadata(ownerType,
                new System.Windows.FrameworkPropertyMetadata(ownerType));

        }
        public ApplicationMenu()
            : base()
        {
          
            this.AppMenuSelectedContentPresenter = new ContentPresenter();
            
            Binding binding = new Binding() { Path = new PropertyPath("SelectedItem.Content"), Source = this, Mode = BindingMode.OneWay };
            
            BindingOperations.SetBinding
                (
                    this.AppMenuSelectedContentPresenter,
                    ContentPresenter.ContentProperty,
                    binding
                );

           
        }
        #endregion

        //------------------------------------------------------
        //
        //  Properties
        //
        //------------------------------------------------------
        #region Properties

        internal DependencyObject InternalSelectedItem { get; set; }

        /// <summary>
        /// Gets or sets application menu's image.
        /// This is a dependency property.
        /// </summary>
        public ImageSource Image
        {
            get { return (ImageSource)GetValue(ImageProperty); }
            set { SetValue(ImageProperty, value); }
        }

        /// <summary>
        /// Identifies UBCon.Ribbon.ApplicationMenu.Image attached property.
        /// </summary>
        public static readonly DependencyProperty ImageProperty = RibbonButton.ImageProperty.AddOwner(typeof(ApplicationMenu));

        /// <summary>
        /// Gets or sets Title for Menu. This is a dependency property.
        /// </summary>
        public string Title
        {
            get { return (string)GetValue(TitleProperty); }
            set { SetValue(TitleProperty, value); }
        }

        /// <summary>
        /// Identifies the UBCon.Ribbon.ApplicationMenu.Title dependency property.
        /// </summary>
        public static readonly DependencyProperty TitleProperty =
            DependencyProperty.Register("Title", typeof(string), typeof(ApplicationMenu), new PropertyMetadata(null));

        /// <summary>
        /// Gets or sets the value of the width of left panel.
        /// </summary>
        public double ItemsPanelWidth
        {
            get { return (double)GetValue(ItemsPanelWidthProperty); }
            set { SetValue(ItemsPanelWidthProperty, value); }
        }

        /// <summary>
        /// Identifies the UBCon.Ribbon.ApplicationMenu.ItemsPanelWidth dependency property.
        /// </summary>
        public static readonly DependencyProperty ItemsPanelWidthProperty =
            DependencyProperty.Register("ItemsPanelWidth", typeof(double), typeof(ApplicationMenu), new PropertyMetadata(double.NaN));

        /// <summary>
        /// Gets or sets a boolean value indicating whether ApplicationMenu is currently open or not.
        /// This is a dependency property.
        /// </summary>
        public bool IsApplicationMenuOpen
        {
            get { return (bool)GetValue(IsApplicationMenuOpenProperty); }
            set { SetValue(IsApplicationMenuOpenProperty, value); }
        }

        /// <summary>
        /// Identifies the UBCon.Ribbon.ApplicationMenu.IsApplicationMenuOpen dependency property.
        /// </summary>
        public static readonly DependencyProperty IsApplicationMenuOpenProperty =
            DependencyProperty.Register("IsApplicationMenuOpen", typeof(bool), typeof(ApplicationMenu),
                    new FrameworkPropertyMetadata(false,
                        FrameworkPropertyMetadataOptions.Journal | FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

        /// <summary>
        /// Gets or sets a boolean value indicating whether the menu is opened with animation or not.
        /// This is a dependency property.
        /// </summary>
        public bool AnimatedOpen
        {
            get { return (bool)GetValue(AnimatedOpenProperty); }
            set { SetValue(AnimatedOpenProperty, value); }
        }

        /// <summary>
        /// Identifies the UBCon.Ribbon.ApplicationMenu.AnimatedOpen dependency property.
        /// </summary>
        public static readonly DependencyProperty AnimatedOpenProperty =
            DependencyProperty.Register("AnimatedOpen", typeof(bool), typeof(ApplicationMenu), new PropertyMetadata(false));

        /// <summary>
        /// Gets or sets the value of menu style.
        /// This is a dependency property.
        /// </summary>
        public ApplicationMenuStyle MenuStyle
        {
            get { return (ApplicationMenuStyle)GetValue(MenuStyleProperty); }
            set { SetValue(MenuStyleProperty, value); }
        }

        /// <summary>
        /// Identifies the UBCon.Ribbon.ApplicationMenu.MenuStyle dependency property.
        /// </summary>
        public static readonly DependencyProperty MenuStyleProperty =
            DependencyProperty.Register("MenuStyle", typeof(ApplicationMenuStyle), typeof(ApplicationMenu),
            new PropertyMetadata(ApplicationMenuStyle.Default, new PropertyChangedCallback(OnMenuStyleChanged)));

        /// <summary>
        /// Gets or sets a boolean value indicating whether menu is drop-down based or not.
        /// </summary>
        public bool IsDropDownMenu
        {
            get { return (bool)GetValue(IsDropDownMenuProperty); }
        }

        /// <summary>
        /// Identifies the UBCon.Ribbon.ApplicationMenu.IsDropDownMenu dependency property key.
        /// </summary>
        internal static readonly DependencyPropertyKey IsDropDownMenuPropertyKey =
            DependencyProperty.RegisterReadOnly("IsDropDownMenu", typeof(bool), typeof(ApplicationMenu), 
            new PropertyMetadata(false));

        /// <summary>
        /// Identifies the UBCon.Ribbon.ApplicationMenu.IsDropDownMenu dependency property.
        /// </summary>
        internal static readonly DependencyProperty IsDropDownMenuProperty = IsDropDownMenuPropertyKey.DependencyProperty;
        
        #endregion

        //------------------------------------------------------
        //
        //  Depenency Property Changed Callbacks
        //
        //------------------------------------------------------
        #region Depenency Property Changed Callbacks

        /// <summary>
        /// Invoked when MenuStyle property changes.
        /// </summary>
        /// <param name="sender">Type: System.Windows.DependencyObject. The DependencyObject on which the property has changed value.</param>
        /// <param name="e">Type: System.Windows.DependencyPropertyChangedEventArgs. Event data that is issued by any event that tracks changes to the effective value of this property.</param>
        private static void OnMenuStyleChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) 
        {
            ApplicationMenu appMenu = sender as ApplicationMenu;
            ApplicationMenuStyle menuStyle = (ApplicationMenuStyle)e.NewValue;
            appMenu.SetValue
                (
                    ApplicationMenu.IsDropDownMenuPropertyKey, 
                    menuStyle == ApplicationMenuStyle.Classic ? true : false
                );
        }

        #endregion

        //------------------------------------------------------
        //
        //  Overrides
        //
        //------------------------------------------------------
        #region Overrieds

        /// <summary>
        ///Creates or identifies the element that is used to display the given item.
        /// </summary>
        /// <returns>Type: System.Windows.DependencyObject. The element that is used to display the given item.</returns>
        protected override DependencyObject GetContainerForItemOverride()
        {
            return new ApplicationMenuItem() 
            { 
                ParentMenu = this 
            };
        }

        /// <summary>
        /// Determines if the specified item is (or is eligible to be) its own ItemContainer. 
        /// (Overrides ItemsControl.IsItemItsOwnContainerOverride(Object).)
        /// </summary>
        /// <param name="item">Specified item.</param>
        /// <returns>true if the item is its own ItemContainer; otherwise, false.</returns>
        protected override bool IsItemItsOwnContainerOverride(object item)
        {
            bool isValidItem = item is ApplicationMenuItem;
            if (isValidItem) 
            {
                ApplicationMenuItem mitem = item as ApplicationMenuItem;
                mitem.ParentMenu = this;
            }
            return isValidItem;
        }

        /// <summary>
        /// Invoked whenever application code or internal processes (such as a rebuilding layout pass) call ApplyTemplate. 
        /// In simplest terms, this means the method is called just before a UI element displays in  app.  
        /// </summary>
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            RootPanel = GetTemplateChild("PART_AppMenuRootPanel") as Grid;
            Border border = GetTemplateChild(AppMenuContentBorderName) as Border;
            if (border != null) 
            {
                border.Child = AppMenuSelectedContentPresenter;
            }
           
        }
        #endregion

        //------------------------------------------------------
        //
        //  Public Methods
        //
        //------------------------------------------------------
        #region Public Methods
        #endregion

        //------------------------------------------------------
        //
        //  Internal Methods
        //
        //------------------------------------------------------
        #region Internal Methods
        #endregion


        //------------------------------------------------------
        //
        //  Private Methods
        //
        //------------------------------------------------------
        #region Private Methods
        #endregion

        //------------------------------------------------------
        //
        //  Event Handlers
        //
        //------------------------------------------------------
        #region Event Handlers
        #endregion

        //------------------------------------------------------
        //
        //  Fields
        //
        //------------------------------------------------------
        #region Fields

        private const string AppMenuContentBorderName="PART_AppMenuContentBorder";
        private const string AppMenuSelectedPresenterName = "PART_AppMenuSelectedPresenter";
        internal RibbonBar _RibbonBar;
        internal ContentPresenter AppMenuSelectedContentPresenter;
        internal Grid RootPanel;
        #endregion

        #region IRibbonControl Implementation

        /// <summary>
        /// Gets a boolean value indicating whether the contol's size is large
        /// </summary>
        public bool IsLarge
        {
            get { return true; }
        }

        #endregion
        
              
    }
}
